#include <GUI/Views/BoardView.hpp>
#include <Core/GPIO.h>
#include <BSP/Fan.h>
#include <BSP/Sensor.h>
#include <BSP/Time.h>
#include <FL/Fl_Window.H>
#include <FL/Fl_Group.H>
#include <FL/fl_draw.H>
#include <cmath>
#include <GUI/Views/CardGroup.hpp>
#include <GUI/Widgets/ValueSlider.hpp>
#include <GUI/Util.hpp>
#include <cstdio>
#include <FL/Fl_Double_Window.H> // 新增：双缓冲窗口


// 根据小时计算温度（简单昼夜曲线：14点最高，2点最低）
static int temp_from_hour(int hour)
{
    if (hour < 0) hour = 0;
    if (hour > 24) hour = 24;
    constexpr double pi = 3.14159265358979323846;
    double rad = (hour - 14) * (2.0 * pi / 24.0);
    double t = 20.0 + 10.0 * std::cos(rad); // 10~30℃
    int ti = static_cast<int>(std::lround(t));
    if (ti < -5) ti = -5;
    if (ti > 35) ti = 35;
    return ti;
}

// 时间滑条回调：设置全局时间，并驱动温度与主题
static void time_slider_cb(Fl_Widget* w, void* userdata)
{
    auto* self = static_cast<BoardView*>(userdata);
    const auto* slider = reinterpret_cast<Fl_Slider*>(w);
    const int hour = static_cast<int>(std::lround(slider->value()));
    time_set_hour(static_cast<uint8_t>(hour));
    if (self && self->time_widget_ptr()) self->time_widget_ptr()->set_hour(static_cast<uint8_t>(hour));
    const int t = temp_from_hour(hour);
    sensor_set_temperature_c(t);
    if (self && self->temp_widget_ptr()) self->temp_widget_ptr()->set_temperature(t);
    if (self) self->apply_theme_for_hour(static_cast<unsigned char>(hour));
}

BoardView::BoardView(int width, int height, const char* title)
{
    // 使用双缓冲窗口以减少GDI闪烁
    main_window = new Fl_Double_Window(width, height, title);
    main_window->color(current_theme_.window_bg);

    time_init();

    // 布局参数
    int margin = 24;
    int pad = 10;
    int card_title_h = 26; // 预留标题高度

    // 卡片统一宽高
    int card_w = 200;
    int card_h = 200;

    // 右侧 2 列网格：上排（窗帘/风扇），下排（时间/温度）
    int right_col2_x = width - card_w - margin; // 右列 x（放风扇/温度）
    int left_col2_x = right_col2_x - card_w - 20; // 左列 x（放窗帘/时间）
    if (left_col2_x < margin) left_col2_x = margin;

    int row1_y = 64; // 上排 y
    int row2_y = row1_y + card_h + 16; // 下排 y

    // 左侧 LED 卡片
    int leds_card_x = margin;
    int leds_card_y = row1_y;
    int leds_card_w = left_col2_x - leds_card_x - 20;
    if (leds_card_w < 4 * 120 + 3 * 12 + 2 * pad)
    {
        leds_card_w = 4 * 120 + 3 * 12 + 2 * pad;
    }
    int leds_card_h = (row2_y + card_h) - leds_card_y;

    auto leds_group = new CardGroup(leds_card_x, leds_card_y, leds_card_w, leds_card_h, "LED");
    card_groups.push_back(leds_group);
    {
        const char* rooms[4] = {"客厅", "卧室", "书房", "厨房"};
        const char* gpios[4] = {"GPIO0", "GPIO1", "GPIO2", "GPIO3"};

        int col_w = 120;
        int img_h = 136;
        int top_h = 20;
        int bottom_h = 22;
        int gap_col = 16;
        int inner_y = leds_card_y + card_title_h + 10;

        int total_w = 4 * col_w + 3 * gap_col;
        int start_x = leds_card_x + (leds_card_w - total_w) / 2;
        if (start_x < leds_card_x + 8) start_x = leds_card_x + 8;

        int widget_h = top_h + img_h + bottom_h;
        int gap_led_switch = 30;
        int switch_h = 100; // 开关高度

        led_widgets.clear();
        switch_widgets.clear();
        for (int i = 0; i < 4; ++i)
        {
            int col_x = start_x + i * (col_w + gap_col);
            // LED：内部自绘顶部/底部文字
            auto led = new LEDWidget(col_x, inner_y, col_w, widget_h, rooms[i], gpios[i]);
            led_widgets.push_back(led);

            // Switch：放在LED下方，宽度同列宽，高度固定
            int sw_y = inner_y + widget_h + gap_led_switch;
            auto sw = new SwitchWidget(col_x, sw_y, col_w, switch_h, i + 4);
            sw->sync_from_port();
            switch_widgets.push_back(sw);
        }
    }
    leds_group->end();

    // 上排：窗帘 + 风扇
    auto curtain_box = new CardGroup(left_col2_x, row1_y, card_w, card_h, "窗帘");
    card_groups.push_back(curtain_box);
    curtain_widget = new CurtainWidget(left_col2_x + pad, row1_y + card_title_h + 20, card_w - 2 * pad,
                                       card_h - card_title_h - pad, "");
    curtain_box->end();

    fan_group_ = new CardGroup(right_col2_x, row1_y, card_w, card_h, "风扇");
    card_groups.push_back(fan_group_);
    fan_widget = new FanWidget(right_col2_x + pad + 5, row1_y + card_title_h + 10, card_w - 2 * pad - 10,
                               card_h - card_title_h - pad - 10, "");
    // 初始化风扇卡片标题
    {
        char buf[64];
        std::snprintf(buf, sizeof(buf), "风扇 档位%d", get_fan());
        fan_group_->copy_label(buf);
    }
    fan_group_->end();

    // 下排：时间 + 温度
    auto* time_box = new CardGroup(left_col2_x, row2_y, card_w, card_h, "时间");
    card_groups.push_back(time_box);
    {
        // 上方是时间显示，下方是滑条
        int content_x = left_col2_x + pad;
        int content_y = row2_y + card_title_h;
        int content_w = card_w - 2 * pad;
        int content_h = card_h - card_title_h - pad;

        int slider_h = 28;
        int slider_gap = 8;
        int time_h = content_h - slider_h - slider_gap;
        if (time_h < 40) { time_h = content_h * 2 / 3; } // 兜底
        int slider_y = content_y + time_h + slider_gap;

        time_widget = new TimeWidget(content_x, content_y, content_w, time_h, "");
        time_widget->set_hour(time_get_hour());

        time_slider = new ValueSlider(content_x, slider_y, content_w, slider_h);
        time_slider->bounds(0, 24);
        time_slider->value(time_get_hour());
        time_slider->callback(time_slider_cb, this);
    }
    time_box->end();

    auto* temp_box = new CardGroup(right_col2_x, row2_y, card_w, card_h, "温度");
    card_groups.push_back(temp_box);
    temp_widget = new TemperatureWidget(right_col2_x + pad, row2_y + card_title_h, card_w - 2 * pad,
                                        card_h - card_title_h - pad, "");
    temp_widget->set_temperature(sensor_get_temperature_c());
    temp_box->end();


    // 初始化一次时间->温度同步
    int init_hour = time_get_hour();
    int init_temp = temp_from_hour(init_hour);
    sensor_set_temperature_c(init_temp);
    temp_widget->set_temperature(init_temp);

    // 初始化一次窗帘状态
    if (curtain_widget) curtain_widget->set_state(false);

    // 应用当前小时主题
    apply_theme_for_hour(static_cast<unsigned char>(init_hour));

    main_window->end();
}

BoardView::~BoardView()
{
    delete main_window;
}

void BoardView::update_states()
{
    for (size_t i = 0; i < led_widgets.size(); ++i)
    {
        if (led_widgets[i])
        {
            const auto [DIR, OUT] = GUI::getGPIOState(i);
            led_widgets[i]->set_state(DIR && OUT);
        }
    }
    // 同步开关显示与端口输入位
    for (const auto& switch_widget : switch_widgets)
    {
        if (switch_widget)
        {
            switch_widget->sync_from_port();
        }
    }
    if (fan_widget)
    {
        int lvl = get_fan();
        fan_widget->set_level(lvl);
        fan_widget->advance();
        fan_widget->redraw();
        if (fan_group_)
        {
            char buf[64];
            std::snprintf(buf, sizeof(buf), "风扇 档位%d", lvl);
            fan_group_->copy_label(buf);
            fan_group_->redraw_label();
        }
    }
    // 保持时间/温度与全局状态同步（若外部修改依然更新 UI）
    if (time_widget)
    {
        auto h = time_get_hour();
        time_widget->set_hour(h);
        int t = temp_from_hour(h);
        sensor_set_temperature_c(t);
        if (temp_widget) temp_widget->set_temperature(t);
    }
    if (curtain_widget)
    {
        auto [DIR, OUT] = GUI::getGPIOState(8);
        curtain_widget->set_state(DIR && OUT);
    }
}

void BoardView::apply_theme_for_hour(unsigned char hour)
{
    current_theme_ = GUI::theme_for_hour(hour);
    GUI::set_current_theme(current_theme_); // 同步全局主题，供各Widget使用
    if (main_window) main_window->color(current_theme_.window_bg);
    for (auto* g : card_groups) if (g) g->set_theme(current_theme_);
    if (main_window) main_window->redraw();
}

void BoardView::show()
{
    main_window->show();
}
